package com.dge.common.aop

import android.app.Activity
import com.blankj.utilcode.util.ToastUtils
import com.hjq.permissions.XXPermissions
import com.dge.common.R
import com.dge.common.manager.ActivityStackManager
import com.dge.common.other.PermissionCallback
import org.aspectj.lang.ProceedingJoinPoint
import org.aspectj.lang.annotation.Around
import org.aspectj.lang.annotation.Aspect
import org.aspectj.lang.annotation.Pointcut
import timber.log.Timber

/**
 * 权限申请切面
 */
@Suppress("unused")
@Aspect
class PermissionsAspect {
    companion object {
        const val NEED_GRANT_ALL = 0 // 需要授予全部权限才能通过
        const val NEED_GRANT_NULL = 1 // 不需要同意任何权限就可以通过
        const val NEED_GRANT_PART = 2 // 授予部分权限就能通过, 这个基本上用不到
    }

    /**
     * 方法切入点
     */
    @Pointcut("execution(@com.dge.common.aop.Permissions * *(..))")
    fun method() {
    }

    /**
     * 在连接点进行方法替换
     */
    @Around("method() && @annotation(permissions)")
    fun aroundJoinPoint(joinPoint: ProceedingJoinPoint, permissions: Permissions) {
        var activity: Activity? = null
        // 方法参数值集合
        val parameterValues: Array<Any?> = joinPoint.args
        for (arg: Any? in parameterValues) {
            if (arg !is Activity) {
                continue
            }
            activity = arg
            break
        }
        if ((activity == null) || activity.isFinishing || activity.isDestroyed) {
            activity = ActivityStackManager.getInstance().getTopActivity()
        }
        if ((activity == null) || activity.isFinishing || activity.isDestroyed) {
            Timber.e("The activity has been destroyed and permission requests cannot be made")
            return
        }
        requestPermissions(joinPoint, activity, permissions.needGrantMode, permissions.value)
    }

    private fun requestPermissions(
        joinPoint: ProceedingJoinPoint,
        activity: Activity,
        needGrantMode: Int,
        permissionList: Array<out String>
    ) {
        if (permissionList.isEmpty()) {
            ToastUtils.showLong(R.string.common_permission_fail_2)
            return
        }
        XXPermissions.with(activity)
            .permission(*permissionList)
            .request(object : PermissionCallback() {
                override fun onGranted(permissions: MutableList<String>, all: Boolean) {
                    Timber.d("onGranted")
                    try {
                        when (needGrantMode) {
                            NEED_GRANT_ALL -> {
                                if (all) {
                                    joinPoint.proceed()// 获得权限，执行原方法
                                }
                            }

                            NEED_GRANT_NULL, NEED_GRANT_PART -> {
                                joinPoint.proceed()// 获得权限，执行原方法
                            }
                        }
                    } catch (e: Throwable) {
                        Timber.e("onGranted: " + e.message)
                    }
                }

                override fun onDenied(permissions: MutableList<String>, never: Boolean) {
                    Timber.d("onDenied")
                    try {
                        when (needGrantMode) {
                            NEED_GRANT_ALL -> {
                                super.onDenied(permissions, never)
                            }

                            NEED_GRANT_PART -> {
                                if (permissionList.size > permissions.size) {
                                    // 还会走进onGrant方法中
                                } else {
                                    super.onDenied(permissions, never)
                                }
                            }

                            NEED_GRANT_NULL -> {
                                if (permissions.size == permissionList.size) {
                                    joinPoint.proceed()// 全拒绝不会走进onGrant方法，着这里通过获得权限，执行原方法
                                }
                                //否则会走进onGrant方法，onGrant中会执行原方法
                            }
                        }
                    } catch (e: Throwable) {
                        Timber.e("onDenied: " + e.message)
                    }
                }
            })
    }
}